package cn.zhentao.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.zhentao.common.Result;
import cn.zhentao.mapper.*;
import cn.zhentao.pojo.*;
import cn.zhentao.util.HttpUtils;
import cn.zhentao.util.JwtUtils;
import cn.zhentao.util.RegexUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.zhentao.service.UserService;

import org.apache.http.HttpResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpSession;
import java.util.Date;

/**
 * @author xm166
 * @description 针对表【user(用户信息表)】的数据库操作Service实现
 * @createDate 2025-07-28 16:25:23
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService, UserDetailsService {
    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RolePermissionMapper rolePermiaaionMapper;
    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired(required = false)
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtUtils jwtUtils;  // 注入JwtUtils

    // 阿里云短信服务配置
    private static final String HOST = "https://gyytz.market.alicloudapi.com";
    private static final String PATH = "/sms/smsSend";
    private static final String METHOD = "POST";
    private static final String APPCODE = "b01a78ea776f451091a4e9ef78ff047b";
    private static final String SMS_SIGN_ID = "2e65b1bb3d054466b82f0c9d125465e2";
    private static final String TEMPLATE_ID = "908e94ccf08b4476ba6c876d13f084ad";


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        wrapper.eq("username",username);
        User user = userMapper.selectOne(wrapper);
        if(user!=null){
            Long id = user.getId();
            QueryWrapper<UserRole> wrapper1=new QueryWrapper<>();
            wrapper1.eq("id", id);  // 兼容表结构：user_role 的用户列为 id
            List<UserRole> userRoles = userRoleMapper.selectList(wrapper1);


            List<Integer> rids=new ArrayList<>();
            for(UserRole userRole:userRoles){
                rids.add(userRole.getRoleId());
            }
            List<Role> roles = roleMapper.selectBatchIds(rids);
            List<String> list=new ArrayList<>();
            for(Role role:roles){
                list.add(role.getRoleName());
            }
            user.setRnames(list);


            QueryWrapper<RolePermission> wrapper2 = new QueryWrapper<>();
            wrapper2.in("role_id", rids);  // 修改字段名为 role_id
            wrapper2.select("permission_id");  // 修改字段名为 permission_id
            List<Object> pids = rolePermiaaionMapper.selectObjs(wrapper2);

            List<Integer> idList = pids.stream()
                    .map(obj -> (Integer) obj)
                    .collect(Collectors.toList());
            List<Permission> permissions = permissionMapper.selectBatchIds(idList);

            List<String> list1 = new ArrayList<>();
            for (Permission permission : permissions) {
                list1.add(permission.getPermissionName());
            }
            user.setPnames(list1);
            return user;
        }

        return null;
    }

    @Override
    public User getUserByUsername(String username) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username); // 修正字段名
        wrapper.eq("del_flag", "0"); // 使用正确的字段名和值类型
        return userMapper.selectOne(wrapper);
    }

    @Override
    public List<Role> getUserRoles(Long userId) {
        QueryWrapper<UserRole> wrapper = new QueryWrapper<>();
        wrapper.eq("id", userId);
        List<UserRole> userRoles = userRoleMapper.selectList(wrapper);

        if (userRoles.isEmpty()) {
            return new ArrayList<>();
        }

        List<Integer> roleIds = userRoles.stream()
                .map(UserRole::getRoleId)
                .collect(Collectors.toList());

        return roleMapper.selectBatchIds(roleIds);
    }

    @Override
    public List<Permission> getUserPermissions(Long userId) {
        // 获取用户角色
        List<Role> roles = getUserRoles(userId);
        if (roles.isEmpty()) {
            return new ArrayList<>();
        }

        List<Long> roleIds = roles.stream()
                .map(Role::getRoleId)
                .collect(Collectors.toList());

        // 获取角色权限
        QueryWrapper<RolePermission> wrapper = new QueryWrapper<>();
        wrapper.in("role_id", roleIds);
        List<RolePermission> rolePermissions = rolePermiaaionMapper.selectList(wrapper);

        if (rolePermissions.isEmpty()) {
            return new ArrayList<>();
        }

        List<Long> permissionIds = rolePermissions.stream()
                .map(RolePermission::getPermissionId)
                .collect(Collectors.toList());

        return permissionMapper.selectBatchIds(permissionIds);
    }

    @Override
    @Transactional
    public boolean assignRolesToUser(Long userId, List<Long> roleIds) {
        // 先删除用户现有角色
        QueryWrapper<UserRole> deleteWrapper = new QueryWrapper<>();
        deleteWrapper.eq("id", userId);
        userRoleMapper.delete(deleteWrapper);

        // 添加新角色
        for (Long roleId : roleIds) {
            UserRole userRole = new UserRole();
            userRole.setUserId(userId.intValue());
            userRole.setRoleId(roleId.intValue());
            userRoleMapper.insert(userRole);
        }

        return true;
    }

    @Override
    @Transactional
    public boolean removeUserRoles(Long userId, List<Long> roleIds) {
        QueryWrapper<UserRole> wrapper = new QueryWrapper<>();
        wrapper.eq("id", userId);
        wrapper.in("role_id", roleIds);
        return userRoleMapper.delete(wrapper) > 0;
    }

    @Override
    public IPage<User> getUserPage(Page<User> page, String username, String status) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();

        if (StringUtils.hasText(username)) {
            wrapper.like("username", username);
        }

        if (StringUtils.hasText(status)) {
            wrapper.eq("status", status);
        }

        wrapper.eq("del_flag", "0"); // 只查询未删除的用户
        wrapper.orderByDesc("create_time");

        return userMapper.selectPage(page, wrapper);
    }

    @Override
    public boolean hasPermission(Long userId, String apiPath, String method) {
        List<Permission> permissions = getUserPermissions(userId);
        if (permissions == null || permissions.isEmpty()) {
            return false;
        }
        // 标准化请求信息
        String reqPath = normalizePath(apiPath);
        String reqMethod = method == null ? "GET" : method.toUpperCase();
        org.springframework.util.AntPathMatcher matcher = new org.springframework.util.AntPathMatcher();
        return permissions.stream().anyMatch(p -> {
            String permPath = normalizePath(p.getApiPath());
            String permMethod = p.getMethod() == null ? "GET" : p.getMethod().toUpperCase();
            return matcher.match(permPath, reqPath) && permMethod.equals(reqMethod);
        });
    }

    private String normalizePath(String path) {
        if (path == null) return "/";
        // 去掉多余斜杠与末尾斜杠
        String s = path.trim();
        if (!s.startsWith("/")) s = "/" + s;
        if (s.endsWith("/") && s.length() > 1) s = s.substring(0, s.length() - 1);
        return s;
    }

    @Override
    public boolean resetPassword(Long userId, String newPassword) {
        User user = new User();
        user.setId(userId);

        if (passwordEncoder != null) {
            user.setPassword(passwordEncoder.encode(newPassword));
        } else {
            user.setPassword(newPassword);
        }

        return userMapper.updateById(user) > 0;
    }
    @Override
    public User getUserByPhone(String phone) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("phonenumber", phone);
        return userMapper.selectOne(wrapper);
    }

    @Override
    public Result<String> sendCode(String phone, HttpSession session) {
        // 1.校验手机号
        if (!isValidPhoneNumber(phone)) {
            return Result.error("手机号格式不正确");
        }

        // 2.检查发送频率限制
        String lastSendTimeKey = "lastSendTime:" + phone;
        Long lastSendTime = (Long) session.getAttribute(lastSendTimeKey);
        // 优化：将频率限制从1分钟改为15秒，与前端倒计时保持一致
        if (lastSendTime != null && System.currentTimeMillis() - lastSendTime < 15000) {
            return Result.error("请求过于频繁，请15秒后再试");
        }

        // 3.生成验证码
        String code = generateVerificationCode();

        try {
            // 4.调用阿里云API发送验证码
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", "APPCODE " + APPCODE);

            Map<String, String> querys = new HashMap<>();
            querys.put("mobile", phone);
            querys.put("param", "**code**:" + code + ",**minute**:5");
            querys.put("smsSignId", SMS_SIGN_ID);
            querys.put("templateId", TEMPLATE_ID);

            Map<String, String> bodys = new HashMap<>();

            HttpResponse response = HttpUtils.doPost(HOST, PATH, METHOD, headers, querys, bodys);

            if (response.getStatusLine().getStatusCode() == 200) {
                // 5.将验证码和发送时间保存到session
                String codeKey = "verifyCode:" + phone;
                session.setAttribute(codeKey, code);
                session.setAttribute(lastSendTimeKey, System.currentTimeMillis());
                
                // 设置验证码5分钟有效期
                session.setMaxInactiveInterval(300);
                
                // 6.记录发送日志（可选）
                log.info("验证码发送成功，手机号：{}，验证码：{}", phone, code);
                
                return Result.success("验证码发送成功");
            } else {
                log.error("验证码发送失败，手机号：{}，HTTP状态码：{}", phone, response.getStatusLine().getStatusCode());
                return Result.error("验证码发送失败");
            }
        } catch (Exception e) {
            log.error("验证码发送异常，手机号：{}，异常信息：{}", phone, e.getMessage(), e);
            return Result.error("验证码发送失败: " + e.getMessage());
        }
    }

    @Override
    public Result<Map<String, Object>> loginByCode(String phone, String code, HttpSession session) {
        // 1.校验手机号格式
        if (!isValidPhoneNumber(phone)) {
            return Result.error("手机号格式不正确");
        }

        // 2.校验验证码
        String codeKey = "verifyCode:" + phone;
        String savedCode = (String) session.getAttribute(codeKey);
        if (savedCode == null) {
            return Result.error("验证码已过期");
        }
        
        if (!savedCode.equals(code)) {
            // 错误次数限制
            String errorCountKey = "verifyCodeErrorCount:" + phone;
            Integer errorCount = (Integer) session.getAttribute(errorCountKey);
            errorCount = errorCount == null ? 1 : errorCount + 1;
            
            if (errorCount >= 5) {
                // 清除验证码，强制重新发送
                session.removeAttribute(codeKey);
                session.removeAttribute(errorCountKey);
                return Result.error("验证码错误次数过多，请重新获取");
            }
            
            session.setAttribute(errorCountKey, errorCount);
            return Result.error("验证码错误");
        }

        // 3.查询用户
        User user = getUserByPhone(phone);
        if (user == null) {
            // 4.如果用户不存在，自动注册
            user = new User();
            user.setPhonenumber(phone);
            user.setUsername(phone); // 默认使用手机号作为用户名
            user.setNickname("用户" + phone.substring(7)); // 使用手机号后4位作为昵称
            user.setPassword(passwordEncoder != null ? passwordEncoder.encode(generateRandomPassword()) : generateRandomPassword()); // 生成随机密码
            user.setStatus(0); // 正常状态
            user.setDelFlag("0"); // 未删除
            user.setUserType("00"); // 默认用户类型
            user.setSex("2"); // 默认性别为未知
            user.setCreateTime(new Date()); // 设置创建时间
            user.setUpdateTime(new Date()); // 设置更新时间
            
            boolean saveResult = save(user);
            if (!saveResult) {
                return Result.error("用户注册失败");
            }
            
            // 重新查询用户，确保获取到完整的用户信息
            user = getUserByPhone(phone);
            if (user == null) {
                return Result.error("用户注册后查询失败");
            }
        }

        // 5.生成token
        String token = generateJwtToken(user);

        // 6.清除验证码和错误计数
        session.removeAttribute(codeKey);
        session.removeAttribute("verifyCodeErrorCount:" + phone);

        // 7.返回结果
        Map<String, Object> data = new HashMap<>();
        data.put("token", token);
        user.setPassword(null); // 清除密码信息
        data.put("user", user);
        return Result.success("登录成功", data);
    }

    // 生成6位随机验证码
    private String generateVerificationCode() {
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            code.append(random.nextInt(10));
        }
        return code.toString();
    }

    // 生成随机密码
    private String generateRandomPassword() {
        return RandomUtil.randomString(12);
    }

    // 校验手机号格式
    private boolean isValidPhoneNumber(String phone) {
        return phone != null && phone.matches("^1[3-9]\\d{9}$");
    }

    @Override
    public String generateJwtToken(User user) {
        if (user == null) {
            throw new IllegalArgumentException("用户信息不能为空");
        }
        
        // 优先使用用户名，如果没有则使用手机号
        String subject = user.getUsername();
        if (subject == null || subject.trim().isEmpty()) {
            subject = user.getPhonenumber();
        }
        
        if (subject == null || subject.trim().isEmpty()) {
            throw new IllegalArgumentException("用户标识信息不能为空");
        }
        
        // 使用增强版JWT令牌生成，包含用户ID
        if (user.getId() != null) {
            return jwtUtils.generateToken(subject, user.getId());
        } else {
            return jwtUtils.generateToken(subject);
        }
    }
}